﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RayTracing
{
    class SharpCone : Geometry
    {
        public bool polar;
        public SharpCone(bool polar)
        {
            this.polar = polar;
        }
        
        public float distance(Ray ray)
        {
            P3 Ro = ray.origin;
            P3 Rd = ray.direction;

            double x0 = Ro.x;
            double y0 = Ro.y;
            double z0 = Ro.z;

            double x1 = Rd.x;
            double y1 = Rd.y;
            double z1 = Rd.z;
            float dist1 = Main.infinity;
            float dist2 = Main.infinity;
            P3 p;

            float d = Main.infinity;

             float discrim1=(float)((2 * x0 * x1 + 2 * y0 * y1 - 2 * z0 * z1) * (2 * x0 * x1 + 2 * y0 * y1 - 2 * z0 * z1) -
       4 * (x0 * x0 + y0 * y0 - z0 * z0) * (x1 * x1 + y1 * y1 - z1 * z1));

            if (discrim1 > 0)
            {
                dist1 = (float)(-2 * x0 * x1 - 2 * y0 * y1 + 2 * z0 * z1 - (float)Math.Sqrt(discrim1)) / (float)(2 * (x1 * x1 + y1 * y1 - z1 * z1));
                p = ray.travel(dist1);
                if (p.z > 1 || p.z < 0)
                {
                    dist1 = Main.infinity;
                }
            }

           
            if (discrim1 > 0)
            {
                dist2 = (float)(-2 * x0 * x1 - 2 * y0 * y1 + 2 * z0 * z1 + Math.Sqrt(discrim1)) / (float)(2 * (x1 * x1 + y1 * y1 - z1 * z1));
                p = ray.travel(dist2);
                if (p.z > 1 || p.z < 0)
                {
                    dist2 = Main.infinity;
                }
            }

            if (dist1 < 0)
            {
                dist1 = Main.infinity;
            }
            if (dist2 < 0)
            {
                dist2 = Main.infinity;
            }


            d = Math.Min(dist1, dist2);



            float t = 0; 
            {
                t = (1 - ray.origin.z) / ray.direction.z;
                if (t > 0)
                {
                    float x = ray.origin.x + t * ray.direction.x;
                    float y = ray.origin.y + t * ray.direction.y;
                    if (Math.Pow(x, 2) + Math.Pow(y, 2) < 1)
                    {
                        d = Math.Min(t, d);
                    }
                }
            }
 
            return d;
        }
        public P3 normal(P3 p)
        {
            if (p.z > .999)
            {
                return new P3(0, 0, 1);
            }
            float newx = 2 * p.x;
            float newy = 2 * p.y;
            float newz = 2 * p.z;

            return new P3(newx, newy, newz);
        }

        public P2 toP2(P3 p)
        {
          
            if ((p.z) > .999)
            {
                return new P2((p.x + 1) / 2, (p.y + 1) / 2, 1);
            }
            if (polar)
            {
                float r = (float)Math.Sqrt( p.x * p.x + p.y * p.y);

                float angle = (float)((Math.Atan(p.y / p.x)+(Math.PI/2))/(Math.PI));

                return new P2(r,angle, 0);
            }
            else
            {
                return new P2((p.x + 1) / 2, (p.y + 1) / 2, 0);
            }
        }


    }

}
